/*
 * loader.c
 *
 *  Created on: 2009-11-30
 *      Author: Bearice
 */
#include <vm.h>
#include <loader.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
uint32 avm_loader_init(PLOADER_STAT stat, uint8* data, uint32 size) {
	stat->data = stat->ptr = data;
	stat->left = stat->size = size;
	return 0;
}
P_SECTION avm_loadder_load_section(PLOADER_STAT stat, P_SECTION buff) {
	buff->tag = readUInt8(stat);
	buff->size = readUInt32(stat);
	buff->data = malloc(buff->size);
	memcpy(buff->data, consumeBytes(stat, buff->size), buff->size);
	return buff;
}
uint32 avm_loader_load_constant(PLOADER_STAT stat, P_CODE code, P_SECTION sect) {
	LOADER_STAT _stat;
	avm_loader_init(&_stat, sect->data, sect->size);
	uint32 lastIdx = code->constant_count;
	DEBUG("Constant.lastIdx=%d\n", code->constant_count);
	code->constant_count += readUInt16(&_stat)-2;
	DEBUG("Constant.length=%d\n", code->constant_count);
	P_CONSTANT lastPtr = code->constants;
	code->constants = malloc(sizeof(A_CONSTANT) * code->constant_count);
	if (lastPtr) {
		memcpy(code->constants, lastPtr, sizeof(A_CONSTANT) + lastIdx);
		free(lastPtr);
	}
	for (uint32 i = lastIdx; i < code->constant_count; i++) {
		P_CONSTANT c = code->constants + i;
		c->tag = readUInt8(&_stat);
		DEBUG("Constant[%d].tag=%d\n", i, c->tag);
		c->size = readUInt16(&_stat);
		DEBUG("Constant[%d].size=%d\n", i, c->size);
		c->data = consumeBytes(&_stat, c->size);
		DEBUG("Constant[%d].data=0x%08x\n", i, c->data);
	}
	DEBUG("==end of constants==\n");
	return 0;
}

P_CODE avm_load_code(uint8* data, uint32 len) {
	P_CODE code = malloc(sizeof(A_CODE));
	memset(code, 0, sizeof(A_CODE));
	LOADER_STAT _stat;
	PLOADER_STAT stat = &_stat;
	avm_loader_init(stat, data, len);
	code->magic = readUInt32(stat);
	DEBUG("code->magic = 0x%08x\n", code->magic);
	code->version = readUInt32(stat);
	DEBUG("code->version = 0x%08x\n", code->version);
	code->entrypoint = readUInt16(stat);
	DEBUG("code->entrypoint = 0x%08x\n", code->entrypoint);
	code->section_count = readUInt16(stat);
	DEBUG("code->section_count = 0x%08x\n", code->section_count);
	code->sections = malloc(code->section_count * sizeof(A_SECTION));
	for (uint32 i = 0; i < code->section_count; i++) {
		P_SECTION s = avm_loadder_load_section(stat, code->sections + i);
		DEBUG("Section[%d].tag=%d\n",i,s->tag);
                DEBUG("Section[%d].tag=%d\n",i,s->size);
                DEBUG("Section[%d].data=0x%08x\n",i,s->data);
		if (s->tag == TAG_CONSTANT) {
			avm_loader_load_constant(stat, code, s);
		}
	}
	return code;
}
